package com.ydl.shopping.security.authentication;

import com.ydl.shopping.async.AsyncTaskService;
import com.ydl.shopping.config.UserPassword;
import com.ydl.shopping.core.entity.LoginUser;
import com.ydl.shopping.domain.TbLoginInfo;
import com.ydl.shopping.exception.ServiceException;
import com.ydl.shopping.service.ITbLoginInfoService;
import com.ydl.shopping.service.ITbUserService;
import com.ydl.shopping.utils.SecurityUtil;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Objects;


/**
 * 账号密码认证器
 *
 * @author 林武泰
 */
@Component
public class UsernamePasswordAuthenticationProvider implements AuthenticationProvider {
    @Resource
    private UserDetailsService userDetailsService;

    @Resource
    private ITbUserService sysUserService;

    @Resource
    private ITbLoginInfoService loginInfoService;

    @Resource
    private UserPassword userPassword;

    @Resource
    private AsyncTaskService asyncTaskService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // 获取用户名
        String username = authentication.getName();

        // 获取密码
        String password = authentication.getCredentials().toString();

        LoginUser userDetails = (LoginUser) userDetailsService.loadUserByUsername(username);

        if (Objects.isNull(userDetails)) {
            throw new UsernameNotFoundException("用户名或密码错误");
        }

        // 获取登录信息
        TbLoginInfo tbLoginInfo = userDetails.getTbLoginInfo();

        if (!SecurityUtil.matchesPassword(password, userDetails.getPassword())) {
            // 密码登录密码错误次数记录
            Long errorRecord = sysUserService.loginErrorRecord(username);
            if (errorRecord > userPassword.getMaxRetryCount()) {
                String message = "密码输入错误"+userPassword.getMaxRetryCount()+"次，帐户锁定"+userPassword.getLockTime()+"分钟";
                tbLoginInfo.setMsg(message);
                // myAsync.execute(new SaveLoginInfoThread(sysLoginInfo, loginInfoService));
                asyncTaskService.execute(p -> loginInfoService.save(p), tbLoginInfo, "新增登录访问");
                throw new ServiceException(message);
            }
            if (errorRecord == 1) {
                String message = "用户名或密码错误";
                tbLoginInfo.setMsg(message);
                // myAsync.execute(new SaveLoginInfoThread(sysLoginInfo, loginInfoService));
                asyncTaskService.execute(p -> loginInfoService.save(p), tbLoginInfo, "新增登录访问");
                throw new UsernameNotFoundException(message);
            }
            String message = "密码输入错误"+errorRecord+"次";
            tbLoginInfo.setMsg(message);
            // myAsync.execute(new SaveLoginInfoThread(sysLoginInfo, loginInfoService));
            asyncTaskService.execute(p -> loginInfoService.save(p), tbLoginInfo, "新增登录访问");
            throw new ServiceException(message);
        }

        // 返回认证的authentication
        UsernamePasswordAuthenticationToken result =
                new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

        result.setDetails(authentication.getDetails());

        return result;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
    }
}
